﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using suirui.ZhuMu.Common;
using suirui.ZhuMu.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace suirui.ZhuMu.WebCore
{
    /// <summary>
    /// 限制请求次数
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class RequestLimitAttribute : ActionFilterAttribute
    {
        public string Name { get; }
        public int NoOfRequest { get; set; }
        public int Seconds { get; set; }

        private static MemoryCache Cache { get; } = new MemoryCache(new MemoryCacheOptions());

        public RequestLimitAttribute(string name, int noOfRequest = 5, int seconds = 10)
        {
            Name = name;
            NoOfRequest = noOfRequest;
            Seconds = seconds;
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var ipAddress = context.HttpContext.Request.HttpContext.Connection.RemoteIpAddress;
            var memoryCacheKey = $"{Name}-{ipAddress}";

            Cache.TryGetValue(memoryCacheKey, out int prevReqCount);
            if (prevReqCount >= NoOfRequest)
            {
                context.Result = new ContentResult
                {
                    Content = $"Request limit is exceeded. Try again in {Seconds} seconds.",
                };
                context.HttpContext.Response.StatusCode = (int)HttpStatusCode.TooManyRequests;
            }
            else
            {
                var cacheEntryOptions = new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromSeconds(Seconds));
                Cache.Set(memoryCacheKey, (prevReqCount + 1), cacheEntryOptions);
            }
        }

        //[HttpGet]
        //[RequestLimit("DataGet", 5, 30)]
        //public IEnumerable<WeatherForecast> Get()
        //{
        //}
    }

    /// <summary>
    /// 防重复提交（接口幂等性）
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class PreventDuplicationRequestAttribute : ActionFilterAttribute
    {
        private int TimeOut = 3;
        private static MemoryCache Cache { get; } = new MemoryCache(new MemoryCacheOptions());

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            string url = context.HttpContext.Request.Path.Value;
            string argument = JsonConvert.SerializeObject(context.ActionArguments);
            string ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
            string agent = context.HttpContext.Request.Headers["User-Agent"];
            string sInfo = $"{url}-{argument}-{ip}-{agent}";
            string summary = MD5Utils.GetMD5(sInfo);
            string KeyPrefix = AppConfigration.Configuration["Encryptionkey"];

            string totalKey = $"{KeyPrefix}-{summary}";

            string result = Cache.Get<string>(totalKey);
            if (string.IsNullOrEmpty(result))
            {
                Cache.Set(totalKey, "1", TimeSpan.FromSeconds(TimeOut));//3秒有效期(3秒内重复请求)                
            }
            else
            {
                context.Result = new JsonResult(new APIResult()
                {
                    Code = ErrorCode.Frequency,
                    Message = $"Request is too frequency. Try again in {TimeOut} seconds.",
                });
            }

            base.OnActionExecuting(context);
        }
    }
}
